Docker can build images automatically by reading the instructions from aDockerfile. A Dockerfile is a text document that contains all the commands auser could call on the command line to assemble an image. This page describesthe commands you can use in a Dockerfile.
OverviewThe Dockerfile supports the following instructions:
InstructionDescriptionADDAdd local or remote files and directories.ARGUse build-time variables.CMDSpecify default commands.COPYCopy files and directories.ENTRYPOINTSpecify default executable.ENVSet environment variables.EXPOSEDescribe which ports your application is listening on.FROMCreate a new build stage from a base image.HEALTHCHECKCheck a container's health on startup.LABELAdd metadata to an image.MAINTAINERSpecify the author of an image.ONBUILDSpecify instructions for when the image is used in a build.RUNExecute build commands.SHELLSet the default shell of an image.STOPSIGNALSpecify the system call signal for exiting a container.USERSet user and group ID.VOLUMECreate volume mounts.WORKDIRChange working directory.FormatHere is the format of the Dockerfile:
# CommentINSTRUCTION argumentsThe instruction is not case-sensitive. However, convention is for them tobe UPPERCASE to distinguish them from arguments more easily.
Docker runs instructions in a Dockerfile in order. A Dockerfile mustbegin with a FROM instruction. This may be afterparserdirectives,comments, and globally scopedARGs. The FROM instruction specifies thebaseimage from which you arebuilding. FROM may only be preceded by one or more ARG instructions, whichdeclare arguments that are used in FROM lines in the Dockerfile.
BuildKit treats lines that begin with # as a comment, unless the line isa validparser directive. A # marker anywhereelse in a line is treated as an argument. This allows statements like:
# CommentRUN echo 'we are running some # of cool things'Comment lines are removed before the Dockerfile instructions are executed.The comment in the following example is removed before the shell executesthe echo command.
RUN echo hello \# commentworldThe following examples is equivalent.
RUN echo hello \worldComments don't support line continuation characters.
Note
Note on whitespace
For backward compatibility, leading whitespace before comments (#) andinstructions (such as RUN) are ignored, but discouraged. Leading whitespaceis not preserved in these cases, and the following examples are thereforeequivalent:
# this is a comment-lineRUN echo helloRUN echo world# this is a comment-lineRUN echo helloRUN echo worldWhitespace in instruction arguments, however, isn't ignored.The following example prints hello worldwith leading whitespace as specified:
RUN echo "\ hello\ world"Parser directivesParser directives are optional, and affect the way in which subsequent linesin a Dockerfile are handled. Parser directives don't add layers to the build,and don't show up as build steps. Parser directives are written as aspecial type of comment in the form # directive=value. A single directivemay only be used once.
The following parser directives are supported:
syntaxescapecheck (since Dockerfile v1.8.0)Once a comment, empty line or builder instruction has been processed, BuildKitno longer looks for parser directives. Instead it treats anything formattedas a parser directive as a comment and doesn't attempt to validate if it mightbe a parser directive. Therefore, all parser directives must be at thetop of a Dockerfile.
Parser directive keys, such as syntax or check, aren't case-sensitive, butthey're lowercase by convention. Values for a directive are case-sensitive andmust be written in the appropriate case for the directive. For example,#check=skip=jsonargsrecommended is invalid because the check name must usePascal case, not lowercase. It's also conventional to include a blank linefollowing any parser directives. Line continuation characters aren't supportedin parser directives.
Due to these rules, the following examples are all invalid:
Invalid due to line continuation:
# direc \tive=valueInvalid due to appearing twice:
# directive=value1# directive=value2FROM ImageNameTreated as a comment because it appears after a builder instruction:
FROM ImageName# directive=valueTreated as a comment because it appears after a comment that isn't a parserdirective:
# About my dockerfile# directive=valueFROM ImageNameThe following unknowndirective is treated as a comment because it isn'trecognized. The known syntax directive is treated as a comment because itappears after a comment that isn't a parser directive.
# unknowndirective=value# syntax=valueNon line-breaking whitespace is permitted in a parser directive. Hence, thefollowing lines are all treated identically:
#directive=value# directive =value#directive= value# directive = value# dIrEcTiVe=valueThe following parser directives are supported:
syntaxescapesyntaxUse the syntax parser directive to declare the Dockerfile syntax version touse for the build. If unspecified, BuildKit uses a bundled version of theDockerfile frontend. Declaring a syntax version lets you automatically use thelatest Dockerfile version without having to upgrade BuildKit or Docker Engine,or even use a custom Dockerfile implementation.
Most users will want to set this parser directive to docker/dockerfile:1,which causes BuildKit to pull the latest stable version of the Dockerfilesyntax before the build.
# syntax=docker/dockerfile:1For more information about how the parser directive works, seeCustom Dockerfile syntax.
escape# escape=\Or
# escape=`The escape directive sets the character used to escape characters in aDockerfile. If not specified, the default escape character is \.
The escape character is used both to escape characters in a line, and toescape a newline. This allows a Dockerfile instruction tospan multiple lines. Note that regardless of whether the escape parserdirective is included in a Dockerfile, escaping is not performed ina RUN command, except at the end of a line.
Setting the escape character to ` is especially useful onWindows, where \ is the directory path separator. ` is consistentwithWindows PowerShell.
Consider the following example which would fail in a non-obvious way onWindows. The second \ at the end of the second line would be interpreted as anescape for the newline, instead of a target of the escape from the first \.Similarly, the \ at the end of the third line would, assuming it was actuallyhandled as an instruction, cause it be treated as a line continuation. The resultof this Dockerfile is that second and third lines are considered a singleinstruction:
FROM microsoft/nanoserverCOPY testfile.txt c:\\RUN dir c:\Results in:
PS E:\myproject> docker build -t cmd .Sending build context to Docker daemon 3.072 kBStep 1/2 : FROM microsoft/nanoserver ---> 22738ff49c6dStep 2/2 : COPY testfile.txt c:\RUN dir c:GetFileAttributesEx c:RUN: The system cannot find the file specified.PS E:\myproject>One solution to the above would be to use / as the target of both the COPYinstruction, and dir. However, this syntax is, at best, confusing as it is notnatural for paths on Windows, and at worst, error prone as not all commands onWindows support / as the path separator.
By adding the escape parser directive, the following Dockerfile succeeds asexpected with the use of natural platform semantics for file paths on Windows:
# escape=`FROM microsoft/nanoserverCOPY testfile.txt c:\RUN dir c:\Results in:
PS E:\myproject> docker build -t succeeds --no-cache=true .Sending build context to Docker daemon 3.072 kBStep 1/3 : FROM microsoft/nanoserver ---> 22738ff49c6dStep 2/3 : COPY testfile.txt c:\ ---> 96655de338deRemoving intermediate container 4db9acbb1682Step 3/3 : RUN dir c:\ ---> Running in a2c157f842f5 Volume in drive C has no label. Volume Serial Number is 7E6D-E0F7 Directory of c:\10/05/2016 05:04 PM 1,894 License.txt10/05/2016 02:22 PM Program Files10/05/2016 02:14 PM Program Files (x86)10/28/2016 11:18 AM62 testfile.txt10/28/2016 11:20 AM Users10/28/2016 11:20 AM Windows2 File(s) 1,956 bytes4 Dir(s) 21,259,096,064 bytes free ---> 01c7f3bef04fRemoving intermediate container a2c157f842f5Successfully built 01c7f3bef04fPS E:\myproject>check# check=skip=# check=error=The check directive is used to configure howbuild checksare evaluated. By default, all checks are run, and failures are treated aswarnings.
You can disable specific checks using #check=skip=. To specifymultiple checks to skip, separate them with a comma:
# check=skip=JSONArgsRecommended,StageNameCasingTo disable all checks, use #check=skip=all.
By default, builds with failing build checks exit with a zero status codedespite warnings. To make the build fail on warnings, set #check=error=true.
# check=error=trueNote
When using the check directive, with error=true option, it is recommendedto pin theDockerfile syntax to a specific version. Otherwise, your build maystart to fail when new checks are added in the future versions.
To combine both the skip and error options, use a semi-colon to separatethem:
# check=skip=JSONArgsRecommended;error=trueTo see all available checks, see thebuild checks reference.Note that the checks available depend on the Dockerfile syntax version. To makesure you're getting the most up-to-date checks, use thesyntaxdirective to specify the Dockerfile syntax version to the latest stableversion.
Environment replacementEnvironment variables (declared withthe ENV statement) can also beused in certain instructions as variables to be interpreted by theDockerfile. Escapes are also handled for including variable-like syntaxinto a statement literally.
Environment variables are notated in the Dockerfile either with$variable_name or ${variable_name}. They are treated equivalently and thebrace syntax is typically used to address issues with variable names with nowhitespace, like ${foo}_bar.
The ${variable_name} syntax also supports a few of the standard bashmodifiers as specified below:
${variable:-word} indicates that if variable is set then the resultwill be that value. If variable is not set then word will be the result.${variable:+word} indicates that if variable is set then word will bethe result, otherwise the result is the empty string.The following variable replacements are supported in a pre-release version ofDockerfile syntax, when using the # syntax=docker/dockerfile-upstream:master syntaxdirective in your Dockerfile:
${variable#pattern} removes the shortest match of pattern from variable,seeking from the start of the string.
str=foobarbaz echo ${str#f*b} # arbaz${variable##pattern} removes the longest match of pattern from variable,seeking from the start of the string.
str=foobarbaz echo ${str##f*b}# az${variable%pattern} removes the shortest match of pattern from variable,seeking backwards from the end of the string.
string=foobarbaz echo ${string%b*}# foobar${variable%%pattern} removes the longest match of pattern from variable,seeking backwards from the end of the string.
string=foobarbaz echo ${string%%b*}# foo${variable/pattern/replacement} replace the first occurrence of patternin variable with replacement
string=foobarbaz echo ${string/ba/fo} # fooforbaz${variable//pattern/replacement} replaces all occurrences of patternin variable with replacement
string=foobarbaz echo ${string//ba/fo} # fooforfozIn all cases, word can be any string, including additional environmentvariables.
pattern is a glob pattern where ? matches any single characterand * any number of characters (including zero). To match literal ? and *,use a backslash escape: \? and \*.
You can escape whole variable names by adding a \ before the variable: \$foo or \${foo},for example, will translate to $foo and ${foo} literals respectively.
Example (parsed representation is displayed after the #):
FROM busyboxENV FOO=/barWORKDIR ${FOO}# WORKDIR /barADD . $FOO# ADD . /barCOPY \$FOO /quux # COPY $FOO /quuxEnvironment variables are supported by the following list of instructions inthe Dockerfile:
ADDCOPYENVEXPOSEFROMLABELSTOPSIGNALUSERVOLUMEWORKDIRONBUILD (when combined with one of the supported instructions above)You can also use environment variables with RUN, CMD, and ENTRYPOINTinstructions, but in those cases the variable substitution is handled by thecommand shell, not the builder. Note that instructions using the exec formdon't invoke a command shell automatically. SeeVariablesubstitution.
Environment variable substitution use the same value for each variablethroughout the entire instruction. Changing the value of a variable only takeseffect in subsequent instructions. Consider the following example:
ENV abc=helloENV abc=bye def=$abcENV ghi=$abcThe value of def becomes helloThe value of ghi becomes bye.dockerignore fileYou can use .dockerignore file to exclude files and directories from thebuild context. For more information, see.dockerignore file.
Shell and exec formThe RUN, CMD, and ENTRYPOINT instructions all have two possible forms:
INSTRUCTION ["executable","param1","param2"] (exec form)INSTRUCTION command param1 param2 (shell form)The exec form makes it possible to avoid shell string munging, and to invokecommands using a specific command shell, or any other executable. It uses aJSON array syntax, where each element in the array is a command, flag, orargument.
The shell form is more relaxed, and emphasizes ease of use, flexibility, andreadability. The shell form automatically uses a command shell, whereas theexec form does not.
Exec formThe exec form is parsed as a JSON array, which means thatyou must use double-quotes (") around words, not single-quotes (').
ENTRYPOINT ["/bin/bash", "-c", "echo hello"]The exec form is best used to specify an ENTRYPOINT instruction, combinedwith CMD for setting default arguments that can be overridden at runtime. Formore information, seeENTRYPOINT.
Variable substitutionUsing the exec form doesn't automatically invoke a command shell. This meansthat normal shell processing, such as variable substitution, doesn't happen.For example, RUN [ "echo", "$HOME" ] won't handle variable substitution for$HOME.
If you want shell processing then either use the shell form or execute a shelldirectly with the exec form, for example: RUN [ "sh", "-c", "echo $HOME" ].When using the exec form and executing a shell directly, as in the case for theshell form, it's the shell that's doing the environment variable substitution,not the builder.
BackslashesIn exec form, you must escape backslashes. This is particularly relevant onWindows where the backslash is the path separator. The following line wouldotherwise be treated as shell form due to not being valid JSON, and fail in anunexpected way:
RUN ["c:\windows\system32\tasklist.exe"]The correct syntax for this example is:
RUN ["c:\\windows\\system32\\tasklist.exe"]Shell formUnlike the exec form, instructions using the shell form always use a commandshell. The shell form doesn't use the JSON array format, instead it's a regularstring. The shell form string lets you escape newlines using theescapecharacter (backslash by default) to continue a single instructiononto the next line. This makes it easier to use with longer commands, becauseit lets you split them up into multiple lines. For example, consider these twolines:
RUN source $HOME/.bashrc && \echo $HOMEThey're equivalent to the following line:
RUN source $HOME/.bashrc && echo $HOMEYou can also use heredocs with the shell form to break up supported commands.
RUN image_versionRUNThe RUN instruction will execute any commands to create a new layer on top ofthe current image. The added layer is used in the next step in the Dockerfile.RUN has two forms:
# Shell form:RUN [OPTIONS] ...# Exec form:RUN [OPTIONS] [ "", ... ]For more information about the differences between these two forms, seeshell or exec forms.
The shell form is most commonly used, and lets you break up longerinstructions into multiple lines, either using newlineescapes, orwithheredocs:
RUN /myvol/greetingVOLUME /myvolThis Dockerfile results in an image that causes docker run tocreate a new mount point at /myvol and copy the greeting fileinto the newly created volume.
Notes about specifying volumesKeep the following things in mind about volumes in the Dockerfile.
Volumes on Windows-based containers: When using Windows-based containers,the destination of a volume inside the container must be one of:
a non-existing or empty directorya drive other than C:Changing the volume from within the Dockerfile: If any build steps change thedata within the volume after it has been declared, those changes will be discarded.
JSON formatting: The list is parsed as a JSON array.You must enclose words with double quotes (") rather than single quotes (').
The host directory is declared at container run-time: The host directory(the mountpoint) is, by its nature, host-dependent. This is to preserve imageportability, since a given host directory can't be guaranteed to be availableon all hosts. For this reason, you can't mount a host directory fromwithin the Dockerfile. The VOLUME instruction does not support specifying a host-dirparameter. You must specify the mountpoint when you create or run the container.
USERUSER [:]or
USER [:]The USER instruction sets the user name (or UID) and optionally the usergroup (or GID) to use as the default user and group for the remainder of thecurrent stage. The specified user is used for RUN instructions and atruntime, runs the relevant ENTRYPOINT and CMD commands.
Note that when specifying a group for the user, the user will have only thespecified group membership. Any other configured group memberships will be ignored.
Warning
When the user doesn't have a primary group then the image (or the nextinstructions) will be run with the root group.
On Windows, the user must be created first if it's not a built-in account.This can be done with the net user command called as part of a Dockerfile.
FROM microsoft/windowsservercore# Create Windows user in the containerRUN net user /add patrick# Set it for subsequent commandsUSER patrickWORKDIRWORKDIR /path/to/workdirThe WORKDIR instruction sets the working directory for any RUN, CMD,ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile.If the WORKDIR doesn't exist, it will be created even if it's not used in anysubsequent Dockerfile instruction.
The WORKDIR instruction can be used multiple times in a Dockerfile. If arelative path is provided, it will be relative to the path of the previousWORKDIR instruction. For example:
WORKDIR /aWORKDIR bWORKDIR cRUN pwdThe output of the final pwd command in this Dockerfile would be /a/b/c.
The WORKDIR instruction can resolve environment variables previously set usingENV. You can only use environment variables explicitly set in the Dockerfile.For example:
ENV DIRPATH=/pathWORKDIR $DIRPATH/$DIRNAMERUN pwdThe output of the final pwd command in this Dockerfile would be/path/$DIRNAME
If not specified, the default working directory is /. In practice, if you aren't building a Dockerfile from scratch (FROM scratch),the WORKDIR may likely be set by the base image you're using.
Therefore, to avoid unintended operations in unknown directories, it's best practice to set your WORKDIR explicitly.
ARGARG [=] [[=]...]The ARG instruction defines a variable that users can pass at build-time tothe builder with the docker build command using the --build-arg =flag.
Warning
It isn't recommended to use build arguments for passing secrets such asuser credentials, API tokens, etc. Build arguments are visible in thedocker history command and in max mode provenance attestations,which are attached to the image by default if you use the Buildx GitHub Actionsand your GitHub repository is public.
Refer to theRUN --mount=type=secret section tolearn about secure ways to use secrets when building images.
A Dockerfile may include one or more ARG instructions. For example,the following is a valid Dockerfile:
FROM busyboxARG user1ARG buildno# ...Default valuesAn ARG instruction can optionally include a default value:
FROM busyboxARG user1=someuserARG buildno=1# ...If an ARG instruction has a default value and if there is no value passedat build-time, the builder uses the default.
ScopeAn ARG variable comes into effect from the line on which it is declared inthe Dockerfile. For example, consider this Dockerfile:
FROM busyboxUSER ${username:-some_user}ARG usernameUSER $username# ...A user builds this file by calling:
$ docker build --build-arg username=what_user .The USER instruction on line 2 evaluates to the some_user fallback,because the username variable is not yet declared.The username variable is declared on line 3, and available for reference inDockerfile instruction from that point onwards.The USER instruction on line 4 evaluates to what_user, since at thatpoint the username argument has a value of what_user which was passed onthe command line. Prior to its definition by an ARG instruction, any use ofa variable results in an empty string.An ARG variable declared within a build stage is automatically inherited byother stages based on that stage. Unrelated build stages do not have access tothe variable. To use an argument in multiple distinct stages, each stage mustinclude the ARG instruction, or they must both be based on a shared basestage in the same Dockerfile where the variable is declared.
For more information, refer tovariable scoping.
Using ARG variablesYou can use an ARG or an ENV instruction to specify variables that areavailable to the RUN instruction. Environment variables defined using theENV instruction always override an ARG instruction of the same name. Considerthis Dockerfile with an ENV and ARG instruction.
FROM ubuntuARG CONT_IMG_VERENV CONT_IMG_VER=v1.0.0RUN echo $CONT_IMG_VERThen, assume this image is built with this command:
$ docker build --build-arg CONT_IMG_VER=v2.0.1 .In this case, the RUN instruction uses v1.0.0 instead of the ARG settingpassed by the user:v2.0.1 This behavior is similar to a shellscript where a locally scoped variable overrides the variables passed asarguments or inherited from environment, from its point of definition.
Using the example above but a different ENV specification you can create moreuseful interactions between ARG and ENV instructions:
FROM ubuntuARG CONT_IMG_VERENV CONT_IMG_VER=${CONT_IMG_VER:-v1.0.0}RUN echo $CONT_IMG_VERUnlike an ARG instruction, ENV values are always persisted in the builtimage. Consider a docker build without the --build-arg flag:
$ docker build .Using this Dockerfile example, CONT_IMG_VER is still persisted in the image butits value would be v1.0.0 as it is the default set in line 3 by the ENV instruction.
The variable expansion technique in this example allows you to pass argumentsfrom the command line and persist them in the final image by leveraging theENV instruction. Variable expansion is only supported fora limited set ofDockerfile instructions.
Predefined ARGsDocker has a set of predefined ARG variables that you can use without acorresponding ARG instruction in the Dockerfile.
HTTP_PROXYhttp_proxyHTTPS_PROXYhttps_proxyFTP_PROXYftp_proxyNO_PROXYno_proxyALL_PROXYall_proxyTo use these, pass them on the command line using the --build-arg flag, forexample:
$ docker build --build-arg HTTPS_PROXY=https://my-proxy.example.com .By default, these pre-defined variables are excluded from the output ofdocker history. Excluding them reduces the risk of accidentally leakingsensitive authentication information in an HTTP_PROXY variable.
For example, consider building the following Dockerfile using--build-arg HTTP_PROXY=http://user:pass@proxy.lon.example.com
FROM ubuntuRUN echo "Hello World"In this case, the value of the HTTP_PROXY variable is not available in thedocker history and is not cached. If you were to change location, and yourproxy server changed to http://user:pass@proxy.sfo.example.com, a subsequentbuild does not result in a cache miss.
If you need to override this behaviour then you may do so by adding an ARGstatement in the Dockerfile as follows:
FROM ubuntuARG HTTP_PROXYRUN echo "Hello World"When building this Dockerfile, the HTTP_PROXY is preserved in thedocker history, and changing its value invalidates the build cache.
Automatic platform ARGs in the global scopeThis feature is only available when using theBuildKitbackend.
BuildKit supports a predefined set of ARG variables with information on the platform ofthe node performing the build (build platform) and on the platform of theresulting image (target platform). The target platform can be specified withthe --platform flag on docker build.
The following ARG variables are set automatically:
TARGETPLATFORM - platform of the build result. Eg linux/amd64, linux/arm/v7, windows/amd64.TARGETOS - OS component of TARGETPLATFORMTARGETARCH - architecture component of TARGETPLATFORMTARGETVARIANT - variant component of TARGETPLATFORMBUILDPLATFORM - platform of the node performing the build.BUILDOS - OS component of BUILDPLATFORMBUILDARCH - architecture component of BUILDPLATFORMBUILDVARIANT - variant component of BUILDPLATFORMThese arguments are defined in the global scope so are not automaticallyavailable inside build stages or for your RUN commands. To expose one ofthese arguments inside the build stage redefine it without value.
For example:
FROM alpineARG TARGETPLATFORMRUN echo "I'm building for $TARGETPLATFORM"BuildKit built-in build argsArgTypeDescriptionBUILDKIT_CACHE_MOUNT_NSStringSet optional cache ID namespace.BUILDKIT_CONTEXT_KEEP_GIT_DIRBoolTrigger Git context to keep the .git directory.BUILDKIT_INLINE_CACHE2BoolInline cache metadata to image config or not.BUILDKIT_MULTI_PLATFORMBoolOpt into deterministic output regardless of multi-platform output or not.BUILDKIT_SANDBOX_HOSTNAMEStringSet the hostname (default buildkitsandbox)BUILDKIT_SYNTAXStringSet frontend imageSOURCE_DATE_EPOCHIntSet the Unix timestamp for created image and layers. More info fromreproducible builds. Supported since Dockerfile 1.5, BuildKit 0.11Example: keep .git dirWhen using a Git context, .git dir is not kept on checkouts. It can beuseful to keep it around if you want to retrieve git information duringyour build:
# syntax=docker/dockerfile:1FROM alpineWORKDIR /srcRUN --mount=target=. \ make REVISION=$(git rev-parse HEAD) build$ docker build --build-arg BUILDKIT_CONTEXT_KEEP_GIT_DIR=1 https://github.com/user/repo.git#mainImpact on build cachingARG variables are not persisted into the built image as ENV variables are.However, ARG variables do impact the build cache in similar ways. If aDockerfile defines an ARG variable whose value is different from a previousbuild, then a "cache miss" occurs upon its first usage, not its definition. Inparticular, all RUN instructions following an ARG instruction use the ARGvariable implicitly (as an environment variable), thus can cause a cache miss.All predefined ARG variables are exempt from caching unless there is amatching ARG statement in the Dockerfile.
For example, consider these two Dockerfile:
FROM ubuntuARG CONT_IMG_VERRUN echo $CONT_IMG_VERFROM ubuntuARG CONT_IMG_VERRUN echo helloIf you specify --build-arg CONT_IMG_VER= on the command line, in bothcases, the specification on line 2 doesn't cause a cache miss; line 3 doescause a cache miss. ARG CONT_IMG_VER causes the RUN line to be identifiedas the same as running CONT_IMG_VER= echo hello, so if the changes, you get a cache miss.
Consider another example under the same command line:
FROM ubuntuARG CONT_IMG_VERENV CONT_IMG_VER=$CONT_IMG_VERRUN echo $CONT_IMG_VERIn this example, the cache miss occurs on line 3. The miss happens becausethe variable's value in the ENV references the ARG variable and thatvariable is changed through the command line. In this example, the ENVcommand causes the image to include the value.
If an ENV instruction overrides an ARG instruction of the same name, likethis Dockerfile:
FROM ubuntuARG CONT_IMG_VERENV CONT_IMG_VER=helloRUN echo $CONT_IMG_VERLine 3 doesn't cause a cache miss because the value of CONT_IMG_VER is aconstant (hello). As a result, the environment variables and values used onthe RUN (line 4) doesn't change between builds.
ONBUILDONBUILDThe ONBUILD instruction adds to the image a trigger instruction tobe executed at a later time, when the image is used as the base foranother build. The trigger will be executed in the context of thedownstream build, as if it had been inserted immediately after theFROM instruction in the downstream Dockerfile.
This is useful if you are building an image which will be used as a baseto build other images, for example an application build environment or adaemon which may be customized with user-specific configuration.
For example, if your image is a reusable Python application builder, itwill require application source code to be added in a particulardirectory, and it might require a build script to be called afterthat. You can't just call ADD and RUN now, because you don't yethave access to the application source code, and it will be different foreach application build. You could simply provide application developerswith a boilerplate Dockerfile to copy-paste into their application, butthat's inefficient, error-prone and difficult to update because itmixes with application-specific code.
The solution is to use ONBUILD to register advance instructions torun later, during the next build stage.
Here's how it works:
When it encounters an ONBUILD instruction, the builder adds atrigger to the metadata of the image being built. The instructiondoesn't otherwise affect the current build.At the end of the build, a list of all triggers is stored in theimage manifest, under the key OnBuild. They can be inspected withthe docker inspect command.Later the image may be used as a base for a new build, using theFROM instruction. As part of processing the FROM instruction,the downstream builder looks for ONBUILD triggers, and executesthem in the same order they were registered. If any of the triggersfail, the FROM instruction is aborted which in turn causes thebuild to fail. If all triggers succeed, the FROM instructioncompletes and the build continues as usual.Triggers are cleared from the final image after being executed. Inother words they aren't inherited by "grand-children" builds.For example you might add something like this:
ONBUILD ADD . /app/srcONBUILD RUN /usr/local/bin/python-build --dir /app/srcCopy or mount from stage, image, or contextAs of Dockerfile syntax 1.11, you can use ONBUILD with instructions that copyor mount files from other stages, images, or build contexts. For example:
# syntax=docker/dockerfile:1.11FROM alpine AS baseimageONBUILD COPY --from=build /usr/bin/app /appONBUILD RUN --mount=from=config,target=/opt/appconfig ...If the source of from is a build stage, the stage must be defined in theDockerfile where ONBUILD gets triggered. If it's a named context, thatcontext must be passed to the downstream build.
ONBUILD limitationsChaining ONBUILD instructions using ONBUILD ONBUILD isn't allowed.The ONBUILD instruction may not trigger FROM or MAINTAINER instructions.STOPSIGNALSTOPSIGNAL signalThe STOPSIGNAL instruction sets the system call signal that will be sent to thecontainer to exit. This signal can be a signal name in the format SIG,for instance SIGKILL, or an unsigned number that matches a position in thekernel's syscall table, for instance 9. The default is SIGTERM if notdefined.
The image's default stopsignal can be overridden per container, using the--stop-signal flag on docker run and docker create.
HEALTHCHECKThe HEALTHCHECK instruction has two forms:
HEALTHCHECK [OPTIONS] CMD command (check container health by running a command inside the container)HEALTHCHECK NONE (disable any healthcheck inherited from the base image)The HEALTHCHECK instruction tells Docker how to test a container to check thatit's still working. This can detect cases such as a web server stuck inan infinite loop and unable to handle new connections, even though the serverprocess is still running.
When a container has a healthcheck specified, it has a health status inaddition to its normal status. This status is initially starting. Whenever ahealth check passes, it becomes healthy (whatever state it was previously in).After a certain number of consecutive failures, it becomes unhealthy.
The options that can appear before CMD are:
--interval=DURATION (default: 30s)--timeout=DURATION (default: 30s)--start-period=DURATION (default: 0s)--start-interval=DURATION (default: 5s)--retries=N (default: 3)The health check will first run interval seconds after the container isstarted, and then again interval seconds after each previous check completes.
If a single run of the check takes longer than timeout seconds then the checkis considered to have failed.
It takes retries consecutive failures of the health check for the containerto be considered unhealthy.
start period provides initialization time for containers that need time to bootstrap.Probe failure during that period will not be counted towards the maximum number of retries.However, if a health check succeeds during the start period, the container is consideredstarted and all consecutive failures will be counted towards the maximum number of retries.
start interval is the time between health checks during the start period.This option requires Docker Engine version 25.0 or later.
There can only be one HEALTHCHECK instruction in a Dockerfile. If you listmore than one then only the last HEALTHCHECK will take effect.
The command after the CMD keyword can be either a shell command (e.g. HEALTHCHECK CMD /bin/check-running) or an exec array (as with other Dockerfile commands;see e.g. ENTRYPOINT for details).
The command's exit status indicates the health status of the container.The possible values are:
0: success - the container is healthy and ready for use1: unhealthy - the container isn't working correctly2: reserved - don't use this exit codeFor example, to check every five minutes or so that a web-server is able toserve the site's main page within three seconds:
HEALTHCHECK --interval=5m --timeout=3s \ CMD curl -f http://localhost/ || exit 1To help debug failing probes, any output text (UTF-8 encoded) that the command writeson stdout or stderr will be stored in the health status and can be queried withdocker inspect. Such output should be kept short (only the first 4096 bytesare stored currently).
When the health status of a container changes, a health_status event isgenerated with the new status.
SHELLSHELL ["executable", "parameters"]The SHELL instruction allows the default shell used for the shell form ofcommands to be overridden. The default shell on Linux is ["/bin/sh", "-c"], and onWindows is ["cmd", "/S", "/C"]. The SHELL instruction must be written in JSONform in a Dockerfile.
The SHELL instruction is particularly useful on Windows where there aretwo commonly used and quite different native shells: cmd and powershell, aswell as alternate shells available including sh.
The SHELL instruction can appear multiple times. Each SHELL instruction overridesall previous SHELL instructions, and affects all subsequent instructions. For example:
FROM microsoft/windowsservercore# Executed as cmd /S /C echo defaultRUN echo default# Executed as cmd /S /C powershell -command Write-Host defaultRUN powershell -command Write-Host default# Executed as powershell -command Write-Host helloSHELL ["powershell", "-command"]RUN Write-Host hello# Executed as cmd /S /C echo helloSHELL ["cmd", "/S", "/C"]RUN echo helloThe following instructions can be affected by the SHELL instruction when theshell form of them is used in a Dockerfile: RUN, CMD and ENTRYPOINT.
The following example is a common pattern found on Windows which can bestreamlined by using the SHELL instruction:
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"The command invoked by the builder will be:
cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"This is inefficient for two reasons. First, there is an unnecessary cmd.execommand processor (aka shell) being invoked. Second, each RUN instruction inthe shell form requires an extra powershell -command prefixing the command.
To make this more efficient, one of two mechanisms can be employed. One is touse the JSON form of the RUN command such as:
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]While the JSON form is unambiguous and does not use the unnecessary cmd.exe,it does require more verbosity through double-quoting and escaping. The alternatemechanism is to use the SHELL instruction and the shell form,making a more natural syntax for Windows users, especially when combined withthe escape parser directive:
# escape=`FROM microsoft/nanoserverSHELL ["powershell","-command"]RUN New-Item -ItemType Directory C:\ExampleADD Execute-MyCmdlet.ps1 c:\example\RUN c:\example\Execute-MyCmdlet -sample 'hello world'Resulting in:
PS E:\myproject> docker build -t shell .Sending build context to Docker daemon 4.096 kBStep 1/5 : FROM microsoft/nanoserver ---> 22738ff49c6dStep 2/5 : SHELL powershell -command ---> Running in 6fcdb6855ae2 ---> 6331462d4300Removing intermediate container 6fcdb6855ae2Step 3/5 : RUN New-Item -ItemType Directory C:\Example ---> Running in d0eef8386e97Directory: C:\Mode LastWriteTime Length Name---- ------------- ------ ----d-----10/28/2016 11:26 AM Example ---> 3f2fbf1395d9Removing intermediate container d0eef8386e97Step 4/5 : ADD Execute-MyCmdlet.ps1 c:\example\ ---> a955b2621c31Removing intermediate container b825593d39fcStep 5/5 : RUN c:\example\Execute-MyCmdlet 'hello world' ---> Running in be6d8e63fe75hello world ---> 8e559e9bf424Removing intermediate container be6d8e63fe75Successfully built 8e559e9bf424PS E:\myproject>The SHELL instruction could also be used to modify the way in whicha shell operates. For example, using SHELL cmd /S /C /V:ON|OFF on Windows, delayedenvironment variable expansion semantics could be modified.
The SHELL instruction can also be used on Linux should an alternate shell berequired such as zsh, csh, tcsh and others.
Here-DocumentsHere-documents allow redirection of subsequent Dockerfile lines to the input ofRUN or COPY commands. If such command contains ahere-documentthe Dockerfile considers the next lines until the line only containing ahere-doc delimiter as part of the same command.
Example: Running a multi-line script# syntax=docker/dockerfile:1FROM debianRUN